package com.flyxteam.commons.reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 反射的常用操作
 * <ul>
 * <li>2017-01-01 | ChrisX | + create</li>
 * </ul>
 * @author ChrisX
 */
public class ReflectUtil {

    public static Object getFieldValueByGetter(Object instance, String fieldName) {
        Method method = getGetter(instance.getClass(), fieldName);
        try {
            return method.invoke(instance);
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

    public static Object setFieldValueBySetter(Object instance, String fieldName, Object value) {
        Method method = getSetter(instance.getClass(), fieldName, value.getClass());
        try {
            return method.invoke(instance, value);
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

    public static Object setFieldNullValueBySetter(Object instance, String fieldName, Class<?> filedType) {
        Method method = getSetter(instance.getClass(), fieldName, filedType);
        try {
            return method.invoke(instance, new Object[] { null });
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }
    
    private static Method getGetter(Class<?> clazz, String fieldName) {
        // 首字母大写
        String fieldMethodName = capitalize(fieldName);
        String methodName1 = "get" + fieldMethodName;
        String methodName2 = "is" + fieldMethodName;
        // 查找get/is方法
        Method method = getMethod(clazz, methodName1);
        if (method == null) {
            method = getMethod(clazz, methodName2);
        }
        // 没有getter
        if (method == null) {
            throw new RuntimeException(
                new NoSuchMethodException(
                    String.format("Can not found the getter of field %s in Class %s ", fieldName, clazz.getName())
                )
            );
        }
        return method;
    }

    private static Method getSetter(Class<?> clazz, String fieldName, Class<?> paramType) {
        // 首字母大写
        String fieldMethodName = capitalize(fieldName);
        String methodName1 = "set" + fieldMethodName;
        // 查找set方法
        Method method = getMethod(clazz, methodName1, paramType);
        // 没有setter
        if (method == null) {
            throw new RuntimeException(
                new NoSuchMethodException(
                    String.format("Can not found the setter of field %s in Class %s ", fieldName, clazz.getName())
                )
            );
        }
        return method;
    }

    private static Method getMethod(Class<? extends Object> clazz, String methodName, Class<?>... parameterTypes) {
        try {
            return clazz.getMethod(methodName, parameterTypes);
        } catch (NoSuchMethodException e) {
            return null;
        } catch (SecurityException e) {
            throw new RuntimeException(e);
        }
    }

    private static String capitalize(String name) {
        if (name == null || name.length() == 0) {
            return name;
        }
        return name.substring(0, 1).toUpperCase() + name.substring(1);
    }
}
